﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using UniRlv.COL;
using UniRlv.Utility;

namespace UniRlv.UI.Main.Widget
{
    public class InFileGenAndSplit
    {
        public List<string> codes1;
        public List<string> codes2;
        public List<string> codes3;
        public List<string> codes4;

        public int ratio43;
        public int ratio32;
        public int ratio21;

        public DateTime tmOpr;
        public DateTime tmProduce;
        public ProductionTask task;

        public string Path2Save;
        public string ErrorString;

        public bool SaveInFile()
        {
            bool bOK = false;

            if (codes1.Count == 0)
            {
                ErrorString = "无数据可导出";
                return false;
            }
            switch (task.tagLevel)
            {
                case 1:
                    bOK = SaveCode1(codes1); break;
                case 2:
                    bOK = SaveCode12( ratio21, codes1, codes2); break;
                case 3:
                    bOK = SaveCode123(ratio21, ratio32, codes1, codes2, codes3); break;
                case 4:
                    bOK = SaveCode1234(ratio21, ratio32, ratio43, codes1, codes2, codes3, codes4); break;
            }
            return bOK;
        }

        private bool SaveCode1234(int ratio21, int ratio32, int ratio43, List<string> codes1, List<string> codes2, List<string> codes3, List<string> codes4)
        {
            if (codes4.Count * ratio43 < codes3.Count)
            {
                ErrorString = "部分三级码没有四级父码";
                return false;
            }

            if (codes3.Count * ratio32 < codes2.Count)
            {
                ErrorString = "部分二级码没有三级包装";
                return false;
            }

            if (codes2.Count * ratio21 != codes1.Count)
            {
                ErrorString = "部分一级码没有二级包装或有零小盒";
                return false;
            }


            XmlElement eleCode;
            XmlElement eleBatch;
            XmlDocument xmlDoc;
            int ratio41 = ratio43 * ratio32 * ratio21;
            int ratio42 = ratio32 * ratio43;
            int ratio31 = ratio21 * ratio32;

            ////计算导出的箱数量
            int nBox = codes1.Count / ratio41;//不允许存在散装一级码，故整包装箱数量就是 一级码数量除以 ratio41

            xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, task.tagRatio);

            eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

            for (int i = 0; i < nBox; i++)
            {//瓶瓶瓶盒-瓶瓶瓶盒-瓶瓶瓶盒……瓶瓶瓶盒箱-瓶瓶瓶盒-瓶瓶瓶盒-瓶瓶瓶盒……瓶瓶瓶盒箱-瓶瓶瓶盒-瓶瓶瓶盒-瓶瓶瓶盒……瓶瓶瓶盒箱托    四级关联

                for (int j = 0; j < ratio43; j++)
                {
                    for (int k = 0; k < ratio32; k++)
                    {
                        for (int l = 0; l < ratio21; l++)
                        {
                            eleCode = xmlDoc.CreateElement("Data");
                            eleCode.SetAttribute("code", codes1[i * ratio41 + j * ratio31 + k * ratio21 + l]);
                            eleBatch.AppendChild(eleCode);
                        }

                        eleCode = xmlDoc.CreateElement("Data");
                        eleCode.SetAttribute("code", codes2[i * ratio42 + j * ratio32 + k]);
                        eleBatch.AppendChild(eleCode);
                    }

                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes3[i * ratio43 + j]);
                    eleBatch.AppendChild(eleCode);

                }

                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes4[i]);
                eleBatch.AppendChild(eleCode);
            }

            if (nBox>0)
            {
                using (StreamWriter sw = new StreamWriter(GetOnePath(Path2Save, 1)))
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Indent = true;
                    settings.IndentChars = "  ";
                    XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                    xmlDoc.Save(xmlWriter);
                    xmlWriter.Close();
                }
            }


            if (codes1.Count>nBox*ratio41)
            {//有零箱

                if (codes2.Count < ratio32 * codes3.Count)
                {//零中盒
                    int nCase = codes2.Count / ratio32;
                    int leftCase = nCase - nBox * ratio43;//减去已包装的中盒
                    string ratio;
                    if (leftCase > 0)
                    {
                        ratio = string.Format("1:{0}:{1}:{2}", leftCase, leftCase * ratio32, leftCase * ratio31);
                        xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, ratio);
                        eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

                        for (int i = nBox * ratio43; i < nCase; i++)
                        {
                            for (int j = 0; j < ratio32; j++)
                            {
                                for (int k = 0; k < ratio21; k++)
                                {
                                    eleCode = xmlDoc.CreateElement("Data");
                                    eleCode.SetAttribute("code", codes1[i * ratio31 + j * ratio21 + k]);
                                    eleBatch.AppendChild(eleCode);
                                }

                                eleCode = xmlDoc.CreateElement("Data");
                                eleCode.SetAttribute("code", codes2[i * ratio32 + j]);
                                eleBatch.AppendChild(eleCode);

                            }

                            eleCode = xmlDoc.CreateElement("Data");
                            eleCode.SetAttribute("code", codes3[i]);
                            eleBatch.AppendChild(eleCode);
                        }

                        eleCode = xmlDoc.CreateElement("Data");
                        eleCode.SetAttribute("code", codes4[nBox]);
                        eleBatch.AppendChild(eleCode);

                        using (StreamWriter sw = new StreamWriter(GetOnePath(Path2Save, 2)))
                        {
                            XmlWriterSettings settings = new XmlWriterSettings();
                            settings.Indent = true;
                            settings.IndentChars = "  ";
                            XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                            xmlDoc.Save(xmlWriter);
                            xmlWriter.Close();
                        }

                        nBox++;
                    }

                    if (nBox<codes4.Count)
                    {
                        ratio = string.Format("1:1:{0}:{1}", codes2.Count - nCase * ratio32, codes1.Count - nCase * ratio31);
                    }
                    else
                    {
                        ratio = string.Format("1:{0}:{1}", codes2.Count - nCase * ratio32, codes1.Count - nCase * ratio31);
                    }

                    xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, ratio);
                    eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

                    //瓶瓶瓶盒-瓶瓶瓶盒-瓶瓶瓶盒……瓶瓶瓶盒箱
                    for (int j = nCase * ratio32; j < codes2.Count; j++)
                    {
                        for (int k = 0; k < ratio21; k++)
                        {
                            eleCode = xmlDoc.CreateElement("Data");
                            eleCode.SetAttribute("code", codes1[j * ratio21 + k]);
                            eleBatch.AppendChild(eleCode);
                        }

                        eleCode = xmlDoc.CreateElement("Data");
                        eleCode.SetAttribute("code", codes2[j]);
                        eleBatch.AppendChild(eleCode);

                    }

                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes3[nCase]);
                    eleBatch.AppendChild(eleCode);

                    if (nBox < codes4.Count)
                    {
                        eleCode = xmlDoc.CreateElement("Data");
                        eleCode.SetAttribute("code", codes4[nBox]);
                        eleBatch.AppendChild(eleCode);
                    }

                    using (StreamWriter sw = new StreamWriter(GetOnePath(Path2Save, 3)))
                    {
                        XmlWriterSettings settings = new XmlWriterSettings();
                        settings.Indent = true;
                        settings.IndentChars = "  ";
                        XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                        xmlDoc.Save(xmlWriter);
                        xmlWriter.Close();
                    }
                }
                else
                {//没有零中盒
                    string ratio = string.Format("1:{0}:{1}:{2}", codes3.Count - nBox * ratio43, codes2.Count - nBox * ratio42, codes1.Count - nBox * ratio41);
                    xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, ratio);
                    eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

                    for (int i = nBox * ratio43; i < codes3.Count; i++)
                    {
                        for (int j = 0; j < ratio32; j++)
                        {
                            for (int k = 0; k < ratio21; k++)
                            {
                                eleCode = xmlDoc.CreateElement("Data");
                                eleCode.SetAttribute("code", codes1[i * ratio31 + j * ratio21 + k]);
                                eleBatch.AppendChild(eleCode);
                            }

                            eleCode = xmlDoc.CreateElement("Data");
                            eleCode.SetAttribute("code", codes2[i * ratio32 + j]);
                            eleBatch.AppendChild(eleCode);

                        }

                        eleCode = xmlDoc.CreateElement("Data");
                        eleCode.SetAttribute("code", codes3[i]);
                        eleBatch.AppendChild(eleCode);
                    }

                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes4[nBox]);
                    eleBatch.AppendChild(eleCode);

                    using (StreamWriter sw = new StreamWriter(GetOnePath(Path2Save, 2)))
                    {
                        XmlWriterSettings settings = new XmlWriterSettings();
                        settings.Indent = true;
                        settings.IndentChars = "  ";
                        XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                        xmlDoc.Save(xmlWriter);
                        xmlWriter.Close();
                    }

                }
            }

            return true;
        }

        private bool SaveCode123(int ratio21, int ratio32, List<string> codes1, List<string> codes2, List<string> codes3)
        {
            if (codes3.Count*ratio32 < codes2.Count)
            {
                ErrorString = "部分二级码没有三级父码";
                return false;
            }

            if (codes2.Count * ratio21 < codes1.Count)
            {
                ErrorString = "部分一级码没有二级父码";
                return false;
            }

            XmlElement eleCode;
            XmlElement eleBatch;
            XmlDocument xmlDoc;
            int ratio31 = ratio32 * ratio21;
            ////计算导出的箱数量
            int nBox = codes1.Count/ ratio31;//不允许存在散装一级码，故整包装箱数量就是 一级码数量除以 ratio31

            xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, task.tagRatio);

            eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

            for (int i = 0; i < nBox; i++)
            {//瓶瓶瓶盒-瓶瓶瓶盒-瓶瓶瓶盒……瓶瓶瓶盒箱
                for (int j = 0; j < ratio32; j++)
                {
                    for (int k = 0; k < ratio21; k++)
                    {
                        eleCode = xmlDoc.CreateElement("Data");
                        eleCode.SetAttribute("code", codes1[i * ratio31 + j * ratio21 + k]);
                        eleBatch.AppendChild(eleCode);
                    }

                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes2[i * ratio32 + j]);
                    eleBatch.AppendChild(eleCode);

                }

                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes3[i]);
                eleBatch.AppendChild(eleCode);
            }

            if (nBox>0)
            {
                using (StreamWriter sw = new StreamWriter(GetOnePath(Path2Save, 1)))
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Indent = true;
                    settings.IndentChars = "  ";
                    XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                    xmlDoc.Save(xmlWriter);
                    xmlWriter.Close();
                }
            }


            if (codes1.Count>nBox* ratio31)
            {//有零箱
                string ratio;
                if (codes1.Count%ratio21!=0)
                {//有零盒:手动零箱后不会出现该情况
                    //ratio = string.Format("1:{0}:{1}", codes2.Count - nBox * ratio21 - 1, codes1.Count - nBox * ratio31);
                    //xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, ratio);

                    ////瓶瓶瓶盒-瓶瓶瓶盒-瓶瓶瓶盒……瓶瓶瓶盒箱
                    //for (int j = nBox * ratio32; j < codes2.Count-1; j++)
                    //{
                    //    for (int k = 0; k < ratio21; k++)
                    //    {
                    //        eleCode = xmlDoc.CreateElement("Data");
                    //        eleCode.SetAttribute("code", codes1[j * ratio21 + k]);
                    //        eleBatch.AppendChild(eleCode);
                    //    }

                    //    eleCode = xmlDoc.CreateElement("Data");
                    //    eleCode.SetAttribute("code", codes2[j]);
                    //    eleBatch.AppendChild(eleCode);

                    //}

                    //eleCode = xmlDoc.CreateElement("Data");
                    //eleCode.SetAttribute("code", codes3[nBox + 1]);
                    //eleBatch.AppendChild(eleCode);


                    //using (StreamWriter sw = new StreamWriter(GetOnePath(Path2Save, 2)))
                    //{
                    //    XmlWriterSettings settings = new XmlWriterSettings();
                    //    settings.Indent = true;
                    //    settings.IndentChars = "  ";
                    //    XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                    //    xmlDoc.Save(xmlWriter);
                    //    xmlWriter.Close();
                    //}

                    ////保存零盒
                    //ratio = string.Format("1:{0}", codes1.Count - (codes2.Count - 1) * ratio21);
                    //xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, ratio);

                    //for (int k = (codes2.Count - 1) * ratio21; k < codes1.Count; k++)
                    //{
                    //    eleCode = xmlDoc.CreateElement("Data");
                    //    eleCode.SetAttribute("code", codes1[k]);
                    //    eleBatch.AppendChild(eleCode);
                    //}

                    //eleCode = xmlDoc.CreateElement("Data");
                    //eleCode.SetAttribute("code", codes2[codes2.Count - 1]);
                    //eleBatch.AppendChild(eleCode);

                    //using (StreamWriter sw = new StreamWriter(GetOnePath(Path2Save, 3)))
                    //{
                    //    XmlWriterSettings settings = new XmlWriterSettings();
                    //    settings.Indent = true;
                    //    settings.IndentChars = "  ";
                    //    XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                    //    xmlDoc.Save(xmlWriter);
                    //    xmlWriter.Close();
                    //}
                }
                else
                {
                    ratio = string.Format("1:{0}:{1}", codes2.Count - nBox * ratio32, codes1.Count - nBox*ratio31);
                    xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, ratio);
                    eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

                    //瓶瓶瓶盒-瓶瓶瓶盒-瓶瓶瓶盒……瓶瓶瓶盒箱
                    for (int j = nBox * ratio32; j<codes2.Count; j++)
                    {
                        for (int k = 0; k < ratio21; k++)
                        {
                            eleCode = xmlDoc.CreateElement("Data");
                            eleCode.SetAttribute("code", codes1[j * ratio21 + k]);
                            eleBatch.AppendChild(eleCode);
                        }

                        eleCode = xmlDoc.CreateElement("Data");
                        eleCode.SetAttribute("code", codes2[j]);
                        eleBatch.AppendChild(eleCode);

                    }

                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes3[nBox]);
                    eleBatch.AppendChild(eleCode);


                    using (StreamWriter sw = new StreamWriter(GetOnePath(Path2Save, 2)))
                    {
                        XmlWriterSettings settings = new XmlWriterSettings();
                        settings.Indent = true;
                        settings.IndentChars = "  ";
                        XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                        xmlDoc.Save(xmlWriter);
                        xmlWriter.Close();
                    }
                }
            }
            return true;
        }

        private bool SaveCode12(int ratio21, List<string> codes1, List<string> codes2)
        {
            XmlElement eleCode;
            XmlElement eleBatch;
            XmlDocument xmlDoc;

            int nBox = codes2.Count;
            nBox = nBox > codes1.Count / ratio21 ? codes1.Count / ratio21 : nBox;

            xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, task.tagRatio);

            eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

            for (int i = 0; i < nBox; i++)
            {//先放瓶码，后放箱码
                for (int j = 0; j < ratio21; j++)
                {
                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes1[i * ratio21 + j]);
                    eleBatch.AppendChild(eleCode);
                }

                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes2[i]);
                eleBatch.AppendChild(eleCode);
            }

            if (nBox>0)
            {
                using (StreamWriter sw = new StreamWriter(GetOnePath(Path2Save, 1)))
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Indent = true;
                    settings.IndentChars = "  ";
                    XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                    xmlDoc.Save(xmlWriter);
                    xmlWriter.Close();
                }
            }


            if (codes2.Count*ratio21>codes1.Count)
            {//有零箱
                if ((codes1.Count % ratio21) == 0)
                {//箱码多了，但无散装一级码
                    return true;
                }

                string ratio = string.Format("1:{0}", codes1.Count - nBox*ratio21);
                xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, ratio);
                eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

                //零散数据
                for (int i = nBox * ratio21; i < (nBox + 1) * ratio21 && i < codes1.Count; i++)
                {
                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes1[i]);
                    eleBatch.AppendChild(eleCode);
                }

                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", codes2[nBox]);
                eleBatch.AppendChild(eleCode);

                using (StreamWriter sw = new StreamWriter(GetOnePath(Path2Save, 2)))
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Indent = true;
                    settings.IndentChars = "  ";
                    XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                    xmlDoc.Save(xmlWriter);
                    xmlWriter.Close();
                }
            }
            else if (codes2.Count * ratio21 < codes1.Count)
            {//散包装
                xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, "1");
                eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

                //零散数据
                for (int i = nBox * ratio21; i < codes1.Count; i++)
                {
                    eleCode = xmlDoc.CreateElement("Data");
                    eleCode.SetAttribute("code", codes1[i]);
                    eleBatch.AppendChild(eleCode);
                }

                using (StreamWriter sw = new StreamWriter(GetOnePath(Path2Save, 2)))
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Indent = true;
                    settings.IndentChars = "  ";
                    XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                    xmlDoc.Save(xmlWriter);
                    xmlWriter.Close();
                }
            }
            else
            {//整包装

            }

            return true;
        }

        private bool SaveCode1(List<string> codes1)
        {
            XmlElement eleCode;
            XmlElement eleBatch;

            XmlDocument xmlDoc = GenInXmlHead(task, tmProduce, tmOpr, "1");

            eleBatch = xmlDoc.SelectSingleNode("DataList/Product/Batch") as XmlElement;

            foreach (string code in codes1)
            {
                eleCode = xmlDoc.CreateElement("Data");
                eleCode.SetAttribute("code", code);
                eleBatch.AppendChild(eleCode);
            }

            using (StreamWriter sw = new StreamWriter(Path2Save))
            {
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;
                settings.IndentChars = "  ";
                XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
                xmlDoc.Save(xmlWriter);
                xmlWriter.Close();
            }

            return true;
        }


        private  XmlDocument GenInXmlHead(ProductionTask t, DateTime tmProduce, DateTime tmOpr, string ratio)
        {
            XmlDocument xmlDoc = new XmlDocument();

            //创建类型声明节点  
            XmlNode node = xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", "");
            xmlDoc.AppendChild(node);
            //创建根节点  
            XmlElement root = xmlDoc.CreateElement("DataList");
            xmlDoc.AppendChild(root);
            root.SetAttribute("corpName", task.company);
            root.SetAttribute("manCode", "19060101");
            root.SetAttribute("dataType", "wareHouseIn");
            root.SetAttribute("version", "1.0");
            root.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            root.SetAttribute("xsi:noNamespaceSchemaLocation", "兽药产品入库数据_生产企业.xsd");


            //Product 节点
            XmlElement eleProduct = xmlDoc.CreateElement("Product");
            eleProduct.SetAttribute("productName", t.tym);
            eleProduct.SetAttribute("pzwh", t.pzwh);
            eleProduct.SetAttribute("packing", t.minTagGG);
            root.AppendChild(eleProduct);

            //batch节点
            XmlElement eleBatch = xmlDoc.CreateElement("Batch");
            eleBatch.SetAttribute("batchNo", t.batch);
            eleBatch.SetAttribute("specification", t.gg);
            eleBatch.SetAttribute("minPackUnit", t.minPackUnit);
            eleBatch.SetAttribute("minTagUnit", t.minTagUnit);
            eleBatch.SetAttribute("tagPackRatio", t.tagPackRatio.ToString());
            eleBatch.SetAttribute("tagRatio", ratio);
            eleBatch.SetAttribute("produceDate", tmProduce.ToString("yyyy-MM-dd"));
            eleBatch.SetAttribute("operator", t.oprator);
            eleBatch.SetAttribute("oprDate", tmOpr.ToString("yyyy-MM-dd"));
            eleBatch.SetAttribute("count", codes1.Count.ToString());;
            eleBatch.SetAttribute("countUnit", "0");

            eleProduct.AppendChild(eleBatch);

            return xmlDoc;
        }

        string GetOnePath(string path, int num)
        {
            string orgName = Path.GetFileNameWithoutExtension(path);
            string name = orgName + "_" + num.ToString();

            return path.Replace(orgName, name);
        }
    }
}
